New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
put __super__ on the prototype #787
Conversation
Yes It's the internal property that CoffeeScript uses to make
The existence of
... and have it work. |
One thing I was thinking of to be fair to the JavaScript users is doing: child.prototype.super = parent.prototype; So the JavaScript'ers could do: this.super.initialize.call(this); |
Unfortunately, Backbone isn't trying to be a JavaScript OOP library ... we're not providing "special" super() semantics in general. This means that in JavaScript, you should be using the standard pattern:
If we did want to be an OOP library -- we would be providing much more sugar than this. |
I propose the creation of a wiki page on CoffeeScript which targets the "How to write coffeescript-compatible libraries in Javascript" |
Yes, that would make a fine wiki page, but let's be clear: Every JavaScript library is compatible with CoffeeScript -- this is simply a convenience so that |
Funny, I never fully understood prototypical inheritance until I used Backbone...but I see people are still running away into their comfort zone. |
+1. Why not give regular JS users the convenience instead of just CS users? Part of backbone's elegance is extending views, collections, etc. and calling the "super" method is part of the territory. |
While @jashkenas said
IMHO it's a super legit use of |
Just my two cents: "no fair" that Backbone adds special code to support |
Model = Backbone.Model.extend
set: (attrs, options) ->
super Doesn't actually work with coffeeScript, it will output the following javascript, which will throw a reference error on var Model;
Model = Backbone.Model.extend({
set: function(attrs, options) {
return set.__super__.constructor.call(this, doesntworkactually);
}
}); |
@tonyxiao I believe what @jashkenas meant was something like the following...? Model = Bakbone.Model.extend()
Model::set = ->
# ...
super which compiles to var Model;
Model = Backbone.Model.extend();
Model.prototype.set = function() {
return Model.__super__.set.apply(this, arguments);
}; |
What about class Model extends Backbone.Model
set: ->
#...
super |
+1 I ended up implementing an invokeSuper() method yesterday which can be used from Backbone hierarchies of classes.
It's usable as a mixin, see the code here: https://gist.github.com/3054503 |
After reading a few articles on this subject, I ended up going with something like this (function(Backbone, _) {
// Extend Backbone Classes with a 'super' function to execute a method of an instance's superclass
_.each(['Collection', 'Model', 'View', 'Router'], function(className) {
Backbone[className].prototype.super = function(funcName) {
var parentPrototype = this.constructor.__super__;
if (parentPrototype && typeof parentPrototype[funcName] === 'function') {
return this.constructor.__super__[funcName].apply(this, _.rest(arguments));
}
};
});
})(Backbone, _); And then invoking it like: var Account = SomeCustomCollection.extend({
initialize: function() {
this.super('initialize');
}
}); Sucks that you have to pass in the method name as an argument, but I like it otherwise. |
For those of use wanting this bit of OOP sugar, this looks promising: https://github.com/lukasolson/Backbone-Super |
@dstibrany: good concise code, but YUI compressor fails because of 'super'. Using '_super' works. Backbone[className].prototype._super = function(funcName) { ... |
No guys, it's not a good idea to use such a "super" method. Let me expose it: var Root = Backbone.Model.extend({
log: function (msg) {
console.log(msg);
}
});
var Screamer = Root.extend({
log: function (msg) {
this.constructor.__super__.log.call(this, msg + '!');
}
});
var SuperScreamer = Screamer.extend({
log: function (msg) {
this.constructor.__super__.log.call(this, 'OH MY GOD, '+msg);
}
});
var aSuperScreamer = new SuperScreamer();
aSuperScreamer.log('Hallo world'); // ERROR: Maximum call stack exceeded. Why? Because |
Just for clarification, if you want to use SuperScreamer.__super__.log.call(this, 'OH MY GOD, '+msg); |
Sorry, I forgot to put the good pattern alongside! |
ES6 Classes are almost out, bringing the built-in ability to call |
Been doing research on extending Backbone and found this interesting bit:
At an initial glance it looks as if it could work this
this.__super__.someMethod
, but in reality you must call it off theconstructor
which is assigned directly above.This patch instead places
__super__
on the prototype.I figure there must be an intentional reason for why its currently set up the way it is. Any elaboration would be great.